package step

import (
	"adam2/internal/properties"
	_interface "adam2/internal/quant/interface"
)

// 优化步骤
type OptimizeStep struct {
	updateOptimizeAccountBeforeSell *_interface.UpdateQuantAccount
	updateOptimizeAccountAfterSell  *_interface.UpdateQuantAccount
	updateOptimizeAccountAfterBuy   *_interface.UpdateQuantAccount
	buyDate                         *_interface.BuyDate
	sellDate                        *_interface.SellDate
	optimizeBuy                     *_interface.Buy
	optimizeSell                    *_interface.Sell
	optimizeDelistSell              *_interface.Sell
	optimizeResolveFailSell         *_interface.Sell
	overweight                      *_interface.Overweight
	underweight                     *_interface.Underweight
	optimizeLog                     *_interface.Log
	calculateOptimizeMaData         *_interface.CalculateData
	calculateOptimizeBiasData       *_interface.CalculateData
}

// 初始化
func (o *OptimizeStep) Init(updateOptimizeAccountBeforeSell *_interface.UpdateQuantAccount, updateOptimizeAccountAfterSell *_interface.UpdateQuantAccount,
	updateOptimizeAccountAfterBuy *_interface.UpdateQuantAccount, buyDate *_interface.BuyDate,
	sellDate *_interface.SellDate, optimizeBuy *_interface.Buy, optimizeSell *_interface.Sell, optimizeDelistSell *_interface.Sell, optimizeResolveFailSell *_interface.Sell,
	overweight *_interface.Overweight, underweight *_interface.Underweight, optimizeLog *_interface.Log, calculateOptimizeMaData *_interface.CalculateData,
	calculateOptimizeBiasData *_interface.CalculateData) {
	o.updateOptimizeAccountBeforeSell = updateOptimizeAccountBeforeSell
	o.updateOptimizeAccountAfterSell = updateOptimizeAccountAfterSell
	o.updateOptimizeAccountAfterBuy = updateOptimizeAccountAfterBuy
	o.buyDate = buyDate
	o.sellDate = sellDate
	o.optimizeBuy = optimizeBuy
	o.optimizeSell = optimizeSell
	o.optimizeDelistSell = optimizeDelistSell
	o.optimizeResolveFailSell = optimizeResolveFailSell
	o.overweight = overweight
	o.underweight = underweight
	o.optimizeLog = optimizeLog
	o.calculateOptimizeMaData = calculateOptimizeMaData
	o.calculateOptimizeBiasData = calculateOptimizeBiasData
}

// 执行
func (o *OptimizeStep) Exec(transactionDate string) {
	if properties.QuantProperties_.EnableOptimizeStep {
		var isSellDate bool = (*o.sellDate).IsSellDate(transactionDate)
		var isBuyDate bool = (*o.buyDate).IsBuyDate(transactionDate)

		// 每日---卖出之前更新optimize_account
		(*o.updateOptimizeAccountBeforeSell).Exec(transactionDate)

		// 每日---卖出之前卖出失败的
		(*o.optimizeResolveFailSell).DoSell(transactionDate)
		// 每日---退市卖出
		(*o.optimizeDelistSell).DoSell(transactionDate)
		// 卖出日---卖出
		if isSellDate {
			(*o.optimizeSell).DoSell(transactionDate)
		}
		// 卖出日---在卖出之后更新optimize_account
		(*o.updateOptimizeAccountAfterSell).Exec(transactionDate)

		// 买入日---买入
		if isBuyDate {
			(*o.optimizeBuy).DoBuy(transactionDate)

			// 买入日---在买入之后更新optimize_account表
			(*o.updateOptimizeAccountAfterBuy).Exec(transactionDate)
		}

		// 如果不是交易日，则判断是否在牛熊线之上；如果牛熊线之上，则加仓；如果在牛熊线之下，则减仓
		if !isBuyDate && !isSellDate {
			//var underweight bool = (*o.underweight).Exec(transactionDate)
			(*o.underweight).Exec(transactionDate)
			// 在卖出之后更新optimize_account
			(*o.updateOptimizeAccountAfterSell).Exec(transactionDate)

			//if !underweight {
			(*o.overweight).Exec(transactionDate)
			// 在买入之后更新optimize_account表
			(*o.updateOptimizeAccountAfterBuy).Exec(transactionDate)
			//}
		}

		// 每日---向表optimize_account_log中插入记录
		(*o.optimizeLog).Exec(transactionDate)

		// 每日---计算基础数据
		(*o.calculateOptimizeMaData).Exec(transactionDate)
		(*o.calculateOptimizeBiasData).Exec(transactionDate)
	}
}
